package com.getpebble.android.common.core.trace;

import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable.Creator;
import android.text.TextUtils;
import com.getpebble.android.Features;
import com.getpebble.android.common.core.util.PblPreferences;
import com.getpebble.android.common.core.util.PblPreferences.PrefKey;
import com.getpebble.android.config.BootConfig;
import com.getpebble.android.core.analytics.DummyUrlConnection;
import io.keen.client.android.AndroidKeenClientBuilder;
import io.keen.client.java.KeenCallback;
import io.keen.client.java.KeenClient;
import io.keen.client.java.KeenLogging;
import io.keen.client.java.KeenProject;
import java.util.HashMap;
import java.util.Map;

public class AnalyticsLogger {
    private static final String TAG = AnalyticsLogger.class.getSimpleName();
    private static boolean sActive = false;
    private static Handler sAnalyticsHandler = null;
    private static HandlerThread sAnalyticsHandlerThread = null;
    private static Context sAppContext = null;
    private static Config sConfig = null;
    private static PebbleDeviceObserver sDeviceObserver = null;
    private static Forwarder sForwarder;
    private static Map<String, Object> sGlobalProperties = new HashMap();
    private static boolean sInitialized = false;
    private static KeenProject sKeenProject = null;
    private static UserObserver sUserObserver = null;

    public static class Config {
        public boolean enabled;
        public String projectId;
        public String writeKey;

        public String toString() {
            return "{ projectId:" + this.projectId + ", " + "writeKey:" + this.writeKey + ", " + "enabled:" + this.enabled + " }";
        }
    }

    public static class Event implements Parcelable {
        public static final Creator<Event> CREATOR = new Creator<Event>() {
            public Event createFromParcel(Parcel in) {
                return new Event(in);
            }

            public Event[] newArray(int size) {
                return new Event[size];
            }
        };
        private String mEventCollection;
        private Map<String, Object> mEventParams;

        private Event(String eventCollection, Map<String, Object> eventParams) {
            this.mEventCollection = eventCollection;
            this.mEventParams = eventParams;
        }

        public int describeContents() {
            return 0;
        }

        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(this.mEventCollection);
            dest.writeMap(this.mEventParams);
        }

        private Event(Parcel in) {
            this.mEventCollection = in.readString();
            this.mEventParams = new HashMap();
            in.readMap(this.mEventParams, getClass().getClassLoader());
        }

        public String getEventCollection() {
            return this.mEventCollection;
        }

        public Map<String, Object> getEventParams() {
            return this.mEventParams;
        }
    }

    public static abstract class Forwarder {
        public abstract void forwardAnalyticsMessage(Event event);

        public abstract void uploadAnalytics();
    }

    public static class InitializationException extends Exception {
    }

    static Map<String, Object> getOrCreateChildMap(Map<String, Object> event, String key) {
        if (event.containsKey(key)) {
            return (Map) event.get(key);
        }
        Map<String, Object> value = new HashMap();
        event.put(key, value);
        return value;
    }

    public static Config createConfig(Context appContext) {
        Config config = new Config();
        config.enabled = new PblPreferences(appContext).getBooleanData(PrefKey.ANALYTICS_OPTIN, true);
        Trace.debug(TAG, "Using bootconfig keen values");
        config.projectId = BootConfig.getInstance().getKeenProjectId();
        config.writeKey = BootConfig.getInstance().getKeenWriteKey();
        return config;
    }

    public static synchronized void initialize(Context appContext, Config config, Forwarder forwarder) throws InitializationException, IllegalStateException {
        synchronized (AnalyticsLogger.class) {
            AndroidLogger.log(Level.DEBUG, TAG, "initialize forwarder = " + forwarder, null);
            if (sInitialized) {
                throw new IllegalStateException("first-time initialize already called");
            }
            sAppContext = appContext;
            sConfig = config;
            sInitialized = true;
            sActive = false;
            sForwarder = forwarder;
            setActive(config.enabled);
        }
    }

    public static synchronized void terminate() {
        synchronized (AnalyticsLogger.class) {
            reset();
        }
    }

    public static synchronized void reinitialize(Config config) throws InitializationException {
        synchronized (AnalyticsLogger.class) {
            if (!sInitialized) {
                throw new IllegalStateException("first-time initialize not called yet");
            } else if (TextUtils.isEmpty(config.projectId) || TextUtils.isEmpty(config.writeKey)) {
                throw new IllegalArgumentException("config cannot have empty project_id (\"" + config.projectId + "\") and/or write key (\"" + config.writeKey + "\")");
            } else {
                AndroidKeenClientBuilder builder = new AndroidKeenClientBuilder(sAppContext);
                if (Features.getAnalyticsStressTest()) {
                    builder.withHttpHandler(new DummyUrlConnection());
                    KeenLogging.enableLogging();
                }
                builder.setMaxRecursiveCalls(8);
                builder.setMaxUploadSizeBytes(750000);
                KeenClient keen = builder.build();
                KeenClient.initialize(keen);
                sKeenProject = new KeenProject(config.projectId, config.writeKey, null);
                keen.setDefaultProject(sKeenProject);
                if (keen.getDefaultProject().getProjectId().equals(config.projectId) && keen.getDefaultProject().getWriteKey().equals(config.writeKey)) {
                    Trace.debug(TAG, "No changes to project values, not reinitializing");
                } else {
                    sConfig = config;
                    sActive = false;
                    setActive(config.enabled);
                }
            }
        }
    }

    private static synchronized void initializeKeen(Config config) {
        synchronized (AnalyticsLogger.class) {
            if (!sInitialized) {
                throw new IllegalStateException("first-time initialize not called yet");
            } else if (TextUtils.isEmpty(config.projectId) || TextUtils.isEmpty(config.writeKey)) {
                throw new IllegalArgumentException("config cannot have empty project_id (\"" + config.projectId + "\") and/or write key (\"" + config.writeKey + "\")");
            } else {
                AndroidKeenClientBuilder builder = new AndroidKeenClientBuilder(sAppContext);
                if (Features.getAnalyticsStressTest()) {
                    builder.withHttpHandler(new DummyUrlConnection());
                    KeenLogging.enableLogging();
                }
                builder.setMaxRecursiveCalls(8);
                builder.setMaxUploadSizeBytes(750000);
                KeenClient keen = builder.build();
                KeenClient.initialize(keen);
                sKeenProject = new KeenProject(config.projectId, config.writeKey, null);
                keen.setDefaultProject(sKeenProject);
                keen.setGlobalProperties(new HashMap());
                try {
                    getOrCreateChildMap(getStaticGlobalProperties(), "app").put("version", sAppContext.getPackageManager().getPackageInfo(sAppContext.getPackageName(), 0).versionName);
                } catch (NameNotFoundException e) {
                    e.printStackTrace();
                }
                sDeviceObserver = new PebbleDeviceObserver(sAppContext);
                sUserObserver = new UserObserver(sAppContext);
                AndroidDevice.addStaticProperties(sAppContext);
                setStaticGlobalProperties();
            }
        }
    }

    public static void logEvent(final String eventCollection, final Map<String, Object> eventParams) {
        if (!isInitialized()) {
            AndroidLogger.log(Level.ERROR, TAG, "Not initialised. Will not log event.", null);
        } else if (sForwarder != null) {
            sForwarder.forwardAnalyticsMessage(new Event(eventCollection, eventParams));
        } else if (eventParams == null || eventParams.isEmpty()) {
            AndroidLogger.log(Level.ERROR, TAG, "Event parameters cannot be null or empty. Will not log event.", null);
        } else if (!isActive()) {
            AndroidLogger.log(Level.DEBUG, TAG, "AnalyticsLogger is not active: will not log event.", null);
        } else if (sAnalyticsHandler == null) {
            AndroidLogger.log(Level.ERROR, TAG, "Error uploading analytics: handler is null", null);
        } else {
            sAnalyticsHandler.post(new Runnable() {
                public void run() {
                    synchronized (AnalyticsLogger.class) {
                        if (AnalyticsLogger.isActive()) {
                            KeenClient keen = KeenClient.client();
                            keen.queueEvent(eventCollection, eventParams);
                            AndroidLogger.log(Level.VERBOSE, AnalyticsLogger.TAG, "Logged analytics event: " + eventCollection, null);
                            return;
                        }
                    }
                }
            });
        }
    }

    public static void uploadAnalytics() {
        if (sForwarder != null) {
            AndroidLogger.log(Level.DEBUG, TAG, "Not framework process; not directly uploading analytics - forward to framework", null);
            sForwarder.uploadAnalytics();
        } else if (!isActive()) {
            AndroidLogger.log(Level.DEBUG, TAG, "uploadAnalytics, not uploading -- not active", null);
        } else if (sAnalyticsHandler == null) {
            AndroidLogger.log(Level.ERROR, TAG, "Error uploading analytics: handler is null", null);
        } else {
            sAnalyticsHandler.post(new Runnable() {
                public void run() {
                    AndroidLogger.log(Level.DEBUG, AnalyticsLogger.TAG, "uploadAnalytics (:framework)", null);
                    synchronized (AnalyticsLogger.class) {
                        if (AnalyticsLogger.isActive()) {
                            KeenClient keen = KeenClient.client();
                            keen.sendQueuedEvents(AnalyticsLogger.sKeenProject, new KeenCallback() {
                                public void onSuccess() {
                                    Trace.debug(AnalyticsLogger.TAG, "All events uploaded successfully.");
                                }

                                public void onFailure(Exception e) {
                                    Trace.error(AnalyticsLogger.TAG, "Failed to upload events to Keen.", e);
                                }
                            });
                            return;
                        }
                        AndroidLogger.log(Level.DEBUG, AnalyticsLogger.TAG, "uploadAnalytics (:framework), not uploading -- not active", null);
                    }
                }
            });
        }
    }

    public static synchronized boolean isInitialized() {
        boolean z;
        synchronized (AnalyticsLogger.class) {
            z = sInitialized;
        }
        return z;
    }

    public static synchronized boolean isActive() {
        boolean z;
        synchronized (AnalyticsLogger.class) {
            z = sActive;
        }
        return z;
    }

    public static synchronized void setActive(boolean active) {
        synchronized (AnalyticsLogger.class) {
            AndroidLogger.log(Level.DEBUG, TAG, "Setting analytics logger active to: " + active, null);
            if (sForwarder != null) {
                AndroidLogger.log(Level.DEBUG, TAG, "Not setting up analytics (keen client/observers); not in framework process", null);
            } else if (!sActive && active) {
                initializeKeen(sConfig);
                sAnalyticsHandler = createHandler();
                sActive = active;
            } else if (sActive && !active) {
                uploadAnalytics();
                if (sDeviceObserver != null) {
                    sDeviceObserver.unregister();
                    sDeviceObserver = null;
                }
                if (sUserObserver != null) {
                    sUserObserver.unregister();
                    sUserObserver = null;
                }
                if (sAnalyticsHandlerThread != null) {
                    sAnalyticsHandler = null;
                    sAnalyticsHandlerThread.quit();
                    sAnalyticsHandlerThread = null;
                }
                sActive = active;
            }
        }
    }

    private static Handler createHandler() {
        if (sAnalyticsHandlerThread == null) {
            sAnalyticsHandlerThread = new HandlerThread("analytics_thread");
            sAnalyticsHandlerThread.start();
        }
        Looper looper = sAnalyticsHandlerThread.getLooper();
        if (looper != null) {
            return new Handler(looper);
        }
        AndroidLogger.log(Level.ERROR, TAG, "Error setting up analytics: looper is null", null);
        return null;
    }

    public static Map<String, Object> getStaticGlobalProperties() {
        return sGlobalProperties;
    }

    static void setStaticGlobalProperties() {
        synchronized (AnalyticsLogger.class) {
            if (isActive()) {
                KeenClient.client().setGlobalProperties(sGlobalProperties);
            }
        }
    }

    public static void reset() {
        sAppContext = null;
        sInitialized = false;
        sActive = false;
        sConfig = null;
        if (sUserObserver != null) {
            sUserObserver.unregister();
            sUserObserver = null;
        }
        if (sDeviceObserver != null) {
            sDeviceObserver.unregister();
            sDeviceObserver = null;
        }
        if (sAnalyticsHandlerThread != null) {
            sAnalyticsHandler = null;
            sAnalyticsHandlerThread.quit();
            sAnalyticsHandlerThread = null;
        }
    }
}
